#ifndef __PAGING_H__
#define __PAGING_H__

#include <types.h>
#include <sys/unistd.h>

#define PAGE_SIZE		0x1000
#define PAGE_MASK		(~(PAGE_SIZE-1))

#define PV_PRESENT       	 0x001	/* present */
#define PV_RD    	     	 0x000	/* read-only */
#define PV_WR         		 0x002	/* writable */
#define PV_KERNEL       	 0x000	/* ring 0 */
#define PV_USER       	 	 0x004	/* ring 3 */
#define PV_ALL        	 	 0x007

#define PAGE_ACCESSED		 0x020
#define PAGE_DIRTY		 	 0x040

#define LOW_MEMORY		 	0x100000
#define BASE_MEMORY		 	0xA0000
#define NUM_LOW_PAGES		 LOW_MEMORY/PAGE_SIZE

#define PAGE_ALIGN(addr)	((addr) & 0xfffff000)
#define PAGE_ALIGN_UP(addr)	((((addr) + PAGE_SIZE - 1) >> 12) << 12)

uint32_t virt_to_page(uint32_t virt, uint32_t pdir);
uint32_t virt_to_phys(uint32_t virt, uint32_t pdir);
void *copy_fromuser(uint32_t, void *, uint32_t, size_t);
void *copy_touser(uint32_t, void *, uint32_t, size_t);
addr_t mem_convert(addr_t, addr_t, size_t);
void paging_init(void);
void identity_map(uint32_t *pagedir, uint32_t pflags);
uint32_t build_pagedir(void);
addr_t new_pagedir(void);
int copy_pagedir(addr_t new_pagedir_addr, addr_t old_pagedir_addr);
int copy_pagetable(addr_t new_table_addr, addr_t old_table_addr);
uint32_t get_pte(uint32_t from, uint32_t pagedir_addr);
void set_pde(uint32_t from, uint32_t pagedir_addr, uint32_t value);
uint32_t get_pde(uint32_t from, uint32_t pagedir_addr);
void set_pte(uint32_t from, uint32_t pagedir_addr, uint32_t pde_flags,
	     uint32_t value);
/*void map_mempage(uint32_t from, uint32_t to, uint32_t pagedir_addr,
		 int pflags);
void unmap_mempage(uint32_t from, uint32_t to, uint32_t pdir);*/
/* from: virtual addr; to : phys addr; */
int map_pages(addr_t, addr_t, addr_t, size_t, uint32_t);
int unmap_pages(addr_t, addr_t, addr_t, size_t);
void load_cr3(uint32_t pagedir);
void enable_paging(void);
void free_pagetables(uint32_t *pdir);

#endif	/* __PAGING_H__ */
